﻿using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Linq;
using System.Text;
using System.Reflection;

using PickGold.Handler;

namespace PickGold.Attributes
{
	/// <summary>
	/// 对于类型库(DLL)程序集，标示其入口点，以便动态加载
	/// </summary>
	[AttributeUsage(AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)]
	public class AssemblyEntryPointAttribute : Attribute
	{
		private Assembly _Assembly;
		private MethodInfo _EntryPoint;

		/// <summary>
		/// 匹配标识符，表示程序集能否被当前程序集识别使用
		/// </summary>
		protected Guid _EqualsID;

		/// <summary>
		/// 
		/// </summary>
		public AssemblyEntryPointAttribute() : this(null) { }
		/// <summary>
		/// 
		/// </summary>
		/// <param name="type"></param>
		public AssemblyEntryPointAttribute(Type type)
		{
			if (type == null)
			{
				this._Assembly = Assembly.GetCallingAssembly();
				this.SetEntryPoint(this._Assembly.EntryPoint);
				return;
			}

			this._Assembly = type.Assembly;
			this.SetEntryPoint(this._Assembly.EntryPoint);
			if (this._EntryPoint != null)
				return;

			var attributes = type.Assembly.GetCustomAttributes(typeof(GuidAttribute), true);
			if (attributes == null || attributes.Length == 0)
				return;

			try
			{
				this._EqualsID = new Guid(((GuidAttribute)attributes[0]).Value);
			}
			catch { }
		}

		/// <summary>
		/// 匹配标识符，表示程序集能否被当前程序集识别使用
		/// </summary>
		public virtual Guid EqualsID
		{
			get
			{
				return this._EqualsID;
			}
		}

		/// <summary>
		/// 加载顺序
		/// </summary>
		public virtual int Index { set; get; }

		/// <summary>
		/// 入口点
		/// </summary>
		public virtual MethodInfo EntryPoint
		{
			get
			{
				return this._EntryPoint;
			}
		}

		/// <summary>
		/// 设置
		/// </summary>
		/// <param name="entryPoint">入口点</param>
		protected void SetEntryPoint(HEntryPointByReturnByArguments entryPoint)
		{
			if (entryPoint == null)
				this.SetEntryPoint(Assembly.GetCallingAssembly().EntryPoint);
			else
				this.SetEntryPoint(entryPoint.Method);
		}

		/// <summary>
		/// 设置
		/// </summary>
		/// <param name="entryPoint">入口点</param>
		protected void SetEntryPoint(HEntryPointByReturnNoArguments entryPoint)
		{
			if (entryPoint == null)
				this.SetEntryPoint(Assembly.GetCallingAssembly().EntryPoint);
			else
				this.SetEntryPoint(entryPoint.Method);
		}

		/// <summary>
		/// 设置
		/// </summary>
		/// <param name="entryPoint">入口点</param>
		protected void SetEntryPoint(HEntryPointNoReturnByArguments entryPoint)
		{
			if (entryPoint == null)
				this.SetEntryPoint(Assembly.GetCallingAssembly().EntryPoint);
			else
				this.SetEntryPoint(entryPoint.Method);
		}

		/// <summary>
		/// 设置
		/// </summary>
		/// <param name="entryPoint">入口点</param>
		protected void SetEntryPoint(HEntryPointNoReturnNoArguments entryPoint)
		{
			if (entryPoint == null)
				this.SetEntryPoint(Assembly.GetCallingAssembly().EntryPoint);
			else
				this.SetEntryPoint(entryPoint.Method);
		}

		private void SetEntryPoint(MethodInfo method)
		{
			this._EntryPoint = method;
			if (method == null)
				return;

			if (this._EqualsID != Guid.Empty && this._EqualsID != Common.UniqueId)
				return;

			var attributes = method.DeclaringType.Assembly.GetCustomAttributes(typeof(GuidAttribute), true);
			if (attributes == null || attributes.Length == 0)
				return;

			try
			{
				this._EqualsID = new Guid(((GuidAttribute)attributes[0]).Value);
			}
			catch { }
		}
	}
}
